﻿using System;

using Outcoder.ComponentModel;

namespace Outcoder.Services.Implementation
{
	/* TODO: [DV] Comment. */
	public partial class LockScreenService : ObservableObject, ILockScreenService
	{
		static readonly string promptedKey = "UserPromptedToAllowRunningUnderLockScreen";
		static readonly string runningEnabledKey = "RunningUnderLockScreenEnabled";
		bool initialized;
		readonly object initializationLock = new object();

		public static string RunningEnabledSettingsKey
		{
			get
			{
				return runningEnabledKey;
			}
		}

		public LockScreenService()
		{
			EnsureInitialized();
		}

		public LockScreenService(bool requiresExplicitInitialization)
		{
			if (!requiresExplicitInitialization)
			{
				EnsureInitialized();
			}
		}

		public void Initialize()
		{
			EnsureInitialized();
		}

		void EnsureInitialized()
		{
			if (!initialized)
			{
				lock (initializationLock)
				{
					if (!initialized)
					{
						InitializeWhenReady();
					}

					initialized = true;
				}
			}
		}

		void HandleFrameUnobscured(object o, EventArgs args)
		{
			RunningUnderLockScreen = false;

			IMessenger messenger;
			if (Dependency.TryResolve<IMessenger>(out messenger))
			{
				messenger.Publish(new LockScreenEvent(LockScreenEvent.LockScreenState.Disengaged));
			}
		}

		bool runningUnderLockScreen;

		public bool RunningUnderLockScreen
		{
			get
			{
				return runningUnderLockScreen;
			}
			private set
			{
				Assign(ref runningUnderLockScreen, value);
			}
		}

		bool runningUnderLockScreenEnabled;

		bool userPrompted;

		public bool UserPrompted
		{
			get
			{
				return userPrompted;
			}
			set
			{
				if (Assign(ref userPrompted, value) == AssignmentResult.Success)
				{
					SaveSetting(promptedKey, value);
				}
			}
		}

		void SaveSetting(string key, object value)
		{
			var settingsService = Dependency.Resolve<ISettingsService, SettingsService>();
			settingsService.SetSetting(key, value);
		}

		public bool RunningUnderLockScreenEnabled
		{
			get
			{
				return runningUnderLockScreenEnabled;
			}
			set
			{
				AssignmentResult result = Assign(ref runningUnderLockScreenEnabled, value);

				if (result == AssignmentResult.Success)
				{
					if (runningUnderLockScreenEnabled)
					{
						EnableRunningUnderLockScreen();
					}
					/* Idle detection mode cannot be enabled until the application is restarted. */

					SaveSetting(runningEnabledKey, runningUnderLockScreenEnabled);
				}
			}
		}
	}

	public class LockScreenEvent
	{
		public LockScreenState State { get; private set; }

		public LockScreenEvent(LockScreenState lockScreenState)
		{
			State = lockScreenState;
		}

		public enum LockScreenState
		{
			Engaged,
			Disengaged
		}
	}
}
